package com.essence.grabiec104.grab.service;

import com.essence.common.model.Packet;
import com.essence.common.model.Substation;
import com.essence.grabiec104.grab.dao.GrabberDao;
import com.essence.grabiec104.grab.dao.AlarmDao;
import com.essence.grabiec104.grab.model.CorrelationPointQuery;
import com.essence.grabiec104.grab.model.PointInfo;
import com.essence.grabiec104.grab.model.SelectFramesParams;
import com.essence.starter.model.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.essence.common.model.Point;

import java.util.List;

@Service
public class GrabberService {
    @Autowired
    private GrabberDao grabberDao;

    @Autowired
    private AlarmDao alarmDao;

    public Page<PointInfo> selectPointInfo(SelectFramesParams params) {
        if (params.getPointAddress() != -1) {
            CorrelationPointQuery query = grabberDao.selectCorrelationPointQuery(params.getPointAddress(), params.getSrcHost());
            if (query != null) {
                params.setRelationAddress(query.getPointGrab());
            } else {
                params.setRelationAddress(-1);
            }
        } else {
            params.setRelationAddress(-1);
        }

        List<PointInfo> pointInfos = grabberDao.selectPointInfos(params);
        int count = grabberDao.selectPointInfoCount(params);
        Page<PointInfo> page = new Page<>(params.getOffset() / params.getLimit() + 1, count, pointInfos);
        return page;
    }

    @Transactional
    public void setPointFilter(List<Point> points) {
        grabberDao.emptyPointFilter();
        for (Point point : points) {
            grabberDao.insertPointFilter(point);
            if (grabberDao.updatePointSetting(point) == 0) {
                grabberDao.insertPointSetting(point);
            }
        }
    }

    @Transactional
    public void setPointRelation(List<CorrelationPointQuery> queries) {
        alarmDao.emptyPointRelation();
        for (CorrelationPointQuery query : queries) {
            alarmDao.insertPointRelation(query);
        }
    }

    /**
     * 根据时间戳删除历史数据
     * 按照外键依赖关系，从子表到父表依次删除数据
     *
     * @param timestamp 时间戳
     */
    @Transactional
    public void deleteHistoryData(long timestamp) {
        // 1. 删除报文点号信息表数据
        grabberDao.deletePointInfoByTimestamp(timestamp);
        // 2. 删除报文表数据
        grabberDao.deletePacketByTimestamp(timestamp);
        // 3. 删除字节帧表数据
        grabberDao.deleteBytesFrameByTimestamp(timestamp);
    }

    /**
     * 保留最近的N条数据，删除其他历史数据
     * 按照外键依赖关系，从子表到父表依次删除数据
     *
     * @param count 需要保留的数据条数
     */
    @Transactional
    public void retainLatestData(int count) {
        // 1. 获取最近的N条数据中ID最小的值
        Long minId = grabberDao.getMinIdOfLatestData(count);
        if (minId == null) {
            return; // 如果没有数据，直接返回
        }

        // 2. 按照外键依赖关系，从子表到父表依次删除数据
        // 2.1 删除报文点号信息表数据
        grabberDao.deletePointInfoByMinId(minId);
        // 2.2 删除报文表数据
        grabberDao.deletePacketByMinId(minId);
        // 2.3 删除字节帧表数据
        grabberDao.deleteBytesFrameByMinId(minId);
    }

    public List<PointInfo> selectPointInfosLatest(int limit) {
        List<PointInfo> pointInfos = grabberDao.selectPointInfosLatest(limit);

        for (PointInfo pointInfo : pointInfos) {
            if (pointInfo.getDirection().equals("Upstream")) {
                Substation sub = grabberDao.selectSubstationByHost(pointInfo.getSrcHost());
                pointInfo.setSubstation(sub);
            } else {
                Substation sub = grabberDao.selectSubstationByHost(pointInfo.getDstHost());
                 pointInfo.setSubstation(sub);
            }
            Packet.TieIdentificationEnum tieIdentificationEnum = Packet.TieIdentificationEnum.fromValue(pointInfo.getTieIdentification());
            pointInfo.setTieIdentificationDesc(tieIdentificationEnum.getDescription());
        }
        return pointInfos;
    }
}
